package com.zhj.agent;

import com.zhj.agent.matcher.NamedMatcher;
import com.zhj.agent.matcher.TypeMatcherFactory;
import com.zhj.agent.support.ClassEnhancePluginDefine;
import com.zhj.agent.resolver.PluginBootstrap;
import com.zhj.agent.resolver.PluginManager;

import net.bytebuddy.agent.builder.AgentBuilder;
import net.bytebuddy.description.type.TypeDescription;
import net.bytebuddy.dynamic.DynamicType;
import net.bytebuddy.utility.JavaModule;

import java.lang.instrument.Instrumentation;
import java.util.List;

import lombok.extern.slf4j.Slf4j;


/**
 * 插件代理启动类
 */
@Slf4j
public class PluginAgent {

    /**
     * Premain 用于JVM刚启动时调用，其执行时应用类文件还未加载到JVM
     *
     * @param args            args
     * @param instrumentation instrumentation 定义好了字节码增强的接口通信
     * @since 1.0.0
     */
    public static void premain(String args, Instrumentation instrumentation) {
        //插件读取器，默认会把 classpath下面的文件加载出来
        PluginManager pluginManager = new PluginManager(new PluginBootstrap().loadPlugins());
        new AgentBuilder.Default()
            .type(TypeMatcherFactory.instance(NamedMatcher.class, pluginManager.getNameMatchDefine()))  //拦截指定的类通过构建 ElementMatcher 元素匹配器
            .transform(new Transformer(pluginManager))
            .installOn(instrumentation);
    }

    /**
     * 用于JVM启动后，在运行时刻加载
     *
     * @param args            args
     * @param instrumentation instrumentation 定义好了字节码增强的接口通信
     */
    public static void agentmain(String args, Instrumentation instrumentation) {

    }

    /**
     * <p>Company: 成都返空汇网络技术有限公司 </p>
     * <p>Description: </p>
     *
     * @author zhonghaijun
     * @version 1.0.0
     * @email "mailto:zhonghaijun@fkhwl.com"
     * @date 2021.12.02 14:00
     * @since 1.0.0
     */
    public static class Transformer implements AgentBuilder.Transformer {

        /** Plugin finder */
        private final PluginManager pluginFinder;

        /**
         * Transformer
         *
         * @param pluginFinder plugin finder
         * @since 1.0.0
         */
        public Transformer(PluginManager pluginFinder) {
            this.pluginFinder = pluginFinder;
        }

        /**
         * Transform
         *
         * @param builder         动态类型
         * @param typeDescription type description
         * @param classLoader     class loader
         * @param javaModule      java module
         * @return the dynamic type . builder
         * @since 1.0.0
         */
        @Override
        public DynamicType.Builder<?> transform(DynamicType.Builder<?> builder,
                                                TypeDescription typeDescription,
                                                ClassLoader classLoader,
                                                JavaModule javaModule) {
            List<ClassEnhancePluginDefine> classEnhancePluginDefines = pluginFinder.find(typeDescription);
            if (classEnhancePluginDefines.size() > 0) {
                DynamicType.Builder<?> newBuilder = builder;
                for (ClassEnhancePluginDefine define : classEnhancePluginDefines) {
                    DynamicType.Builder<?> possibleNewBuilder = define.define(builder, classLoader);
                    if (possibleNewBuilder != null) {
                        newBuilder = possibleNewBuilder;
                    }
                }
                return newBuilder;
            }
            return builder;
        }
    }

}
